package com.kobeliu.service.impl;

import com.github.pagehelper.PageInfo;
import com.kobeliu.base.BaseInfoProperties;
import com.kobeliu.enums.JobStatus;
import com.kobeliu.exceptions.GraceException;
import com.kobeliu.pojo.Job;
import com.kobeliu.pojo.bo.CandFollowHrBO;
import com.kobeliu.pojo.bo.HrReadCandBO;
import com.kobeliu.pojo.eo.SearchResumesEO;
import com.kobeliu.pojo.mo.*;
import com.kobeliu.pojo.vo.SearchJobsVO;
import com.kobeliu.repository.HrCollectRepository;
import com.kobeliu.repository.WhoLookMeRepository;
import com.kobeliu.result.GraceJSONResult;
import com.kobeliu.result.ResponseStatusEnum;
import com.kobeliu.service.CountsService;
import com.kobeliu.service.JobService;
import com.kobeliu.service.ResumeSearchService;
import com.kobeliu.utils.LocalDateUtils;
import com.kobeliu.utils.PagedGridResult;
import com.mongodb.client.result.DeleteResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.C;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.ArrayOperators;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import javax.print.attribute.standard.JobState;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CountsServiceImpl extends BaseInfoProperties implements CountsService {


    @Autowired
    private HrCollectRepository hrCollectRepository;
    @Autowired
    private WhoLookMeRepository whoLookMeRepository;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private ResumeSearchService resumeSearchService;

    @Autowired
    private JobService jobService;

    @Override
    public void addCollect(String hrId, String resumeExpectId) {

        HrCollectResumeMO mo = new HrCollectResumeMO();
        mo.setHrId(hrId);
        mo.setResumeExpectId(resumeExpectId);
        mo.setCreateTime(LocalDateTime.now());

        hrCollectRepository.save(mo);

        redis.increment(HR_COLLECT_RESUME_COUNTS+":"+hrId,1);
    }

    @Override
    public void removeCollect(String hrId, String resumeExpectId) {

        hrCollectRepository.deleteByHrIdAndResumeExpectId(hrId,resumeExpectId);
        redis.decrement(HR_COLLECT_RESUME_COUNTS+":"+hrId,1);

    }

    @Override
    public boolean isHrCollectResume(String hrId, String resumeExpectId) {
        List<HrCollectResumeMO> mos = hrCollectRepository.findByHrIdAndResumeExpectId(hrId, resumeExpectId);

        if(mos == null || mos.size()==0){
            return false;
        }
        return true;

    }

    @Override
    public Integer getColletResumeCounts(String hrId) {

        int counts= 0;
        String countStr = redis.get(HR_COLLECT_RESUME_COUNTS + ":" + hrId);
        if(countStr!=null){
            counts = Integer.parseInt(countStr);
        }
        return counts;

    }

    @Override
    public PagedGridResult pagedCollectJobList(String candUserId, Integer page, Integer pageSize) {

        //根据userID去，mongodb中拿取到对应的jobId 之后去es/db中拿取 对应的 details
        Query query = new Query();
        query.addCriteria(Criteria.where("cand_user_id").is(candUserId));

        //分页前先查总数
        long total = mongoTemplate.count(query, CandCollectJobMO.class);

        //分页
        Pageable pageable = PageRequest.of(page,pageSize,Sort.Direction.DESC,"create_time");
        query.with(pageable);

        List<CandCollectJobMO> mos = mongoTemplate.find(query, CandCollectJobMO.class);

        List<String> jobIds = mos.stream().map(CandCollectJobMO::getJobId)
                .collect(Collectors.toList());

        //根据jobIds去db中拿取数据
        if(jobIds!= null && jobIds.size()>0){
            List<SearchJobsVO> jobs = jobService.selectJobDetailsByIds(jobIds, JobStatus.OPEN);

            PagedGridResult result = new PagedGridResult();
            result.setTotal(total);
            result.setRows(jobs);
            result.setPage(page+1);
            result.setRecords(total);

            return result;
        }
        return new PagedGridResult();
    }

    @Override
    public PagedGridResult pagedCollectResumeList(String hrId, Integer page, Integer pageSize) {



        Query query = new Query();
        query.addCriteria(Criteria.where("hr_id").is(hrId));

        //查一个总数
        Long count = mongoTemplate.count(query, HrCollectResumeMO.class);

        Pageable pageable = PageRequest.of(page,pageSize);
        query.with(pageable);
        List<HrCollectResumeMO> mos = mongoTemplate.find(query, HrCollectResumeMO.class);

        List<String> ids = mos.stream()
                .map(HrCollectResumeMO::getResumeExpectId)
                .collect(Collectors.toList());

        //拿到数据，去es中拿取detail
        List<SearchResumesEO> eos = resumeSearchService.listResumeEOs(ids);

        //添加hr收藏该简历的时间
        eos = eos.stream().map(obj->{
            for (HrCollectResumeMO mo:mos){
                if(mo.getResumeExpectId().equalsIgnoreCase(obj.getResumeExpectId())){
                    obj.setHrCollectResumeTime(LocalDateUtils
                            .format(mo.getCreateTime(),
                                    LocalDateUtils.DATETIME_PATTERN)
                    );
                }
            }
            return obj;
        }).collect(Collectors.toList());


//        PageInfo<HrCollectResumeMO> infos = new PageInfo<>();
        PagedGridResult result = new PagedGridResult();
        result.setRows(eos);
        result.setTotal(count);
        result.setRecords(count);
        result.setPage(page+1);

        return result;

    }

    @Override
    public void addReadResumeRecord(String hrId, String resumeExpectId) {

        if(hrId != null || resumeExpectId != null){

            //先看当前的记录在mongodb中存不存在
            Query query = new Query();
            query.addCriteria(Criteria.where("hr_id").is(hrId));
            query.addCriteria(Criteria.where("resume_expect_id").is(resumeExpectId));

            long count = mongoTemplate.count(query, HrReadResumeRecordMO.class);
            if(count==0L){

                redis.increment(HR_READ_RESUME_RECORD_COUNTS+":"+hrId,1);

                //创建一条数据到mongodb中
                HrReadResumeRecordMO mo = new HrReadResumeRecordMO();
                mo.setResumeExpectId(resumeExpectId);
                mo.setHrId(hrId);
                mo.setCreateTime(LocalDateTime.now());
                mongoTemplate.save(mo);

            }
        }
    }

    @Override
    public long getReadResumeRecordCounts(String hrId) {

        long count = 0L;
        String countStr = redis.get(HR_READ_RESUME_RECORD_COUNTS+":"+hrId);
        if(countStr!=null){
            count = Long.parseLong(countStr);
        }
        return count;
    }

    @Override
    public long hrJobCounts(String hrId) {

        String countStr = redis.get(HR_ALL_JOB_COUNTS+":"+hrId);
        if(countStr == null){
            long count = jobService.getJobCounts(hrId);

            redis.set(HR_ALL_JOB_COUNTS+":"+hrId, Long.toString(count));

            return count;
        }

        return Long.parseLong(countStr);
    }

    @Override
    public PagedGridResult pagedReadResumeRecordList(String hrId, Integer page, Integer limit) {
        //mongeDB中拿数据中的 resumeExpectId
        Query query = new Query();
        query.addCriteria(Criteria.where("hr_id").is(hrId));

        //拿取总数
        long count = mongoTemplate.count(query, HrReadResumeRecordMO.class);

        Pageable pageable = PageRequest.of(page,limit, Sort.Direction.DESC,"create_time");
        query.with(pageable);
        List<HrReadResumeRecordMO> mos = mongoTemplate.find(query, HrReadResumeRecordMO.class);

        List<String> ids = mos.stream()
                .map(HrReadResumeRecordMO::getResumeExpectId)
                .collect(Collectors.toList());
        List<SearchResumesEO> eos = resumeSearchService.pagedReadResumeRecordList(ids);

        eos = eos.stream().map(obj ->{
            for(HrReadResumeRecordMO mo:mos){
                if(Objects.equals(mo.getResumeExpectId(), obj.getResumeExpectId())){
                    obj.setHrReadResumeTime(LocalDateUtils.format(mo.getCreateTime(), LocalDateUtils.DATETIME_PATTERN));
                }
            }
            return obj;
        }).collect(Collectors.toList());

        PagedGridResult result = new PagedGridResult();
        result.setRows(eos);
        result.setRecords(count);
        result.setTotal(count);
        result.setPage(page+1);
        return result;
    }

    @Override
    public void hrLookCand(HrReadCandBO bo) {

        //数据存到mongodb中
        if(bo != null){
            String candUserId = bo.getCandUserId();
            String hrId = bo.getHrId();

            Query query = new Query();
            query.addCriteria(Criteria.where("cand_user_id").is(candUserId));
            query.addCriteria(Criteria.where("hr_id").is(hrId));

            long count = mongoTemplate.count(query, WhoLookMeMO.class);
            if(count == 0){
                WhoLookMeMO mo = new WhoLookMeMO();
                //存入数据
                BeanUtils.copyProperties(bo,mo);
                mo.setCreateTime(LocalDateTime.now());
                mongoTemplate.save(mo);

                //添加数量到redis
                redis.increment(WHO_LOOK_ME_COUNTS+":"+candUserId,1);
            }
        }
    }

    @Override
    public long getWhoLookMeCounts(String candUserId) {

        String countStr = redis.get(WHO_LOOK_ME_COUNTS + ":" + candUserId);

        //防止redis爆炸
        if(countStr == null){
            Query query = new Query();
            query.addCriteria(Criteria.where("cand_user_id").is(candUserId));
            long count = mongoTemplate.count(query, WhoLookMeMO.class);

            //放入redis
            redis.set(WHO_LOOK_ME_COUNTS + ":" + candUserId,String.valueOf(count));

            return count;
        }
        return Long.parseLong(countStr);
    }

    @Override
    public PagedGridResult pagedWhoLookMe(String candUserId, Integer page, Integer pageSize) {

        Query query = new Query();
        query.addCriteria(Criteria.where("cand_user_id").is(candUserId));
        //分页前查询一次总数
        long total = mongoTemplate.count(query, WhoLookMeMO.class);

        Pageable pageable = PageRequest.of(page,pageSize,
                Sort.Direction.DESC,
                "create_time");
        query.with(pageable);

        List<WhoLookMeMO> mos = mongoTemplate.find(query, WhoLookMeMO.class);
        PagedGridResult result = new PagedGridResult();
        result.setRows(mos);
        result.setTotal(total);
        result.setPage(page+1);
        result.setRecords(total);
        return result;
    }

    @Override
    public void addCollectJob(String candUserId, String jobId) {


        CandCollectJobMO mo = new CandCollectJobMO();
        mo.setJobId(jobId);
        mo.setCandUserId(candUserId);
        mo.setCreateTime(LocalDateTime.now());
        mongoTemplate.save(mo);

        redis.increment(CAND_COLLECT_JOB_COUNTS+":"+candUserId,1);
    }

    @Override
    public void followHr(CandFollowHrBO bo) {

        if(bo!=null){
            String candUserId = bo.getCandUserId();
            String hrId = bo.getHrId();
            if(StringUtils.isNotBlank(candUserId)
                    && StringUtils.isNotBlank(hrId)){
                Query query = new Query();
                query.addCriteria(Criteria.where("hr_id").is(hrId));
                query.addCriteria(Criteria.where("cand_user_id").is(candUserId));

                long count = mongoTemplate.count(query, CandFollowHrMO.class);
                if(count == 0){
                    //创建
                    CandFollowHrMO mo = new CandFollowHrMO();
                    BeanUtils.copyProperties(bo,mo);
                    mo.setCreateTime(LocalDateTime.now());
                    mongoTemplate.save(mo);

                    redis.increment(CAND_FOLLOW_HR_COUNTS+":"+candUserId,1);
                }
            }
        }


    }

    @Override
    public void unfollowHr(String hrId, String candUserId) {

        if(StringUtils.isNotBlank(candUserId)
                && StringUtils.isNotBlank(hrId)) {
            Query query = new Query();
            query.addCriteria(Criteria.where("hr_id").is(hrId));
            query.addCriteria(Criteria.where("cand_user_id").is(candUserId));

            //删除记录
            DeleteResult remove = mongoTemplate.remove(query, CandFollowHrMO.class);
            if(remove.getDeletedCount()==1){
                redis.decrement(CAND_FOLLOW_HR_COUNTS+":"+candUserId,1);
            }
        }else{
            GraceException.display(ResponseStatusEnum.USER_STATUS_ERROR);
        }

    }

    @Override
    public long getCandFollowHrCounts(String candUserId) {

        String countStr = redis.get(CAND_FOLLOW_HR_COUNTS + ":" + candUserId);

        if(countStr!=null){
            return Long.parseLong(countStr);
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("cand_user_id").is(candUserId));
        long count = mongoTemplate.count(query, CandFollowHrMO.class);

        //放入redis
        redis.set(CAND_FOLLOW_HR_COUNTS + ":" + candUserId,String.valueOf(count));

        return count;
    }

    @Override
    public PagedGridResult pagedCandFollowHr(String candUserId, Integer page, Integer pageSize) {

        Query query = new Query();
        query.addCriteria(Criteria.where("cand_user_id").is(candUserId));
        //分页前查询一次总数
        long total = mongoTemplate.count(query, CandFollowHrMO.class);

        Pageable pageable = PageRequest.of(page,pageSize,
                Sort.Direction.DESC,
                "create_time");
        query.with(pageable);

        List<CandFollowHrMO> mos = mongoTemplate.find(query, CandFollowHrMO.class);
        PagedGridResult result = new PagedGridResult();
        result.setRows(mos);
        result.setTotal(total);
        result.setPage(page+1);
        result.setRecords(total);
        return result;
    }

    @Override
    public boolean doseCandFollowHr(String hrId, String candUserId) {

        Query query = new Query();
        query.addCriteria(Criteria.where("cand_user_id").is(candUserId));
        query.addCriteria(Criteria.where("hr_id").is(hrId));
        //分页前查询一次总数
        long total = mongoTemplate.count(query, CandFollowHrMO.class);

        return total != 0L;
    }

    @Override
    public void removeCollectJob(String candUserId, String jobId) {

        Query query = new Query();
        query.addCriteria(Criteria.where("cand_user_id").is(candUserId));
        query.addCriteria(Criteria.where("job_id").is(jobId));

        DeleteResult remove = mongoTemplate.remove(query, CandCollectJobMO.class);
        if(remove.getDeletedCount() != 0){
            redis.decrement(CAND_COLLECT_JOB_COUNTS+":"+candUserId,1);
        }
    }

    @Override
    public Long getCollectJobCounts(String candUserId) {

        String countStr = redis.get(CAND_COLLECT_JOB_COUNTS + ":" + candUserId);
        if(countStr == null){
            //去mongoDB中确认一下
            Query query = new Query();
            query.addCriteria(Criteria.where("cand_user_id").is(candUserId));
            long count = mongoTemplate.count(query, CandCollectJobMO.class);
            redis.set(CAND_COLLECT_JOB_COUNTS + ":" + candUserId,String.valueOf(count));
            return count;
        }
        return Long.parseLong(countStr);
    }

    @Override
    public boolean isCandCollectJob(String candUserId, String jobId) {

        Query query = new Query();
        query.addCriteria(Criteria.where("cand_user_id").is(candUserId));
        query.addCriteria(Criteria.where("job_id").is(jobId));

        List<CandCollectJobMO> mos = mongoTemplate.find(query, CandCollectJobMO.class);

        return mos.size()>0;
    }

    @Override
    public Long candGetInterviewRecordCounts(String candUserId) {
        String countStr = redis.get(CAND_INTERVIEW_RECORD_COUNTS + ":" + candUserId);

        return countStr==null?0:Long.parseLong(countStr);
    }

    @Override
    public Long hrGetInterviewRecordCounts(String hrId) {
        String countStr = redis.get(HR_INTERVIEW_RECORD_COUNTS + ":" + hrId);

        return countStr==null?0:Long.parseLong(countStr);
    }
}
